#include "Player.hh"
#include <iostream>
#include <algorithm>
#include <sstream> 

Player::Player(std::string name)
    : Character(name, "The adventurer", 20, 20, 5, 2,100), 
      level(1),                                   
      currentXP(0),                                
      nextLevelXP(100),
      mana(0),
      Maxmana(100),
      skill(false){}

void Player::gainExperience(int xp) {
    currentXP += xp;
    std::cout << "Gained " << xp << " experience points.\n";
    while (currentXP >= nextLevelXP) {
        levelUp();
    }
}

void Player::gainMoney(int my){
    money+=my;
    std::cout << "Gained " << my<< " gold coin\n";
}

void Player::addItemToInventory(Item* item) {
    inventory.push_back(item);
    std::cout << "Added " << item->getName() << " to inventory.\n";
}

void Player::applyItemEffects(const Item& item) {
    attacks += item.getAttackBonus();
    defense += item.getDefenseBonus();
    mana+=item.getManaBonus();
    health = std::min(health + item.getHealBonus(), maxHealth);
}

bool Player::useItem(Item* item) {
    auto it = std::find(inventory.begin(), inventory.end(), item);
    if (it != inventory.end()) {
        std::cout << "Used " << item->getName() << ".\n";
        applyItemEffects(*item);
        inventory.erase(it); 
        return true;
    }
    return false;
}

bool Player::soldItem(Item* item) {
    auto it = std::find(inventory.begin(), inventory.end(), item);
    if (it != inventory.end()) {
        std::cout << "sell " << item->getName() <<" and you get"<<item->getValue()<<" gold coin" <<".\n";
        gainMoney(item->getValue());
        inventory.erase(it);
        return true;
    }
    return false;
}
void Player::manaup(){
    mana=std::min(20+mana,Maxmana);
    if (mana==Maxmana){
        std::cout<<"Max mana,now you can use skill"<<".\n";
        skill=true;
    }
    else{
    std::cout << "Gained 20 mana\n";
}
}
void Player::levelUp() {
    currentXP -= nextLevelXP;
    level++;
    nextLevelXP = static_cast<int>(nextLevelXP * 1.5); 
    maxHealth += 10;
    health = maxHealth; 
    attacks += 2; 
    defense += 2; 
    std::cout << "Leveled up! Now at level " << level << ".\n";
}

std::string Player::toString() const{   
    std::stringstream ss;
    ss << name << "\n"
       << "HP: " << health << "/" << maxHealth << "\n"
       << "ATK: " << attacks << "\n"
       << "DEF: " << defense << "\n"
       <<"MANA: "<<mana<<"\n"
       << "MONEY: "<<money<<"\n"
       <<"LEVEL: "<< level  <<"\n"
       <<"XP TO NEXT LEVEL: "<< nextLevelXP-currentXP <<"\n";

       
    return ss.str();
}

int Player::getmana() const
{
    return mana;
}

int Player::getMaxmana() const
{
    return Maxmana;
}

bool Player::getskill() const
{
    return skill;
}

void Player::skillreset() {
    skill = false;
    mana=0;
}

Player Player::operator+(const Player &buff){   
    Player tempPlayer(*this); 
    tempPlayer.attacks += buff.attacks; 
    return tempPlayer; 
}
Player Player::operator-(const Player &buff){   
    Player tempPlayer(*this); 
    tempPlayer.attacks -= buff.attacks; 
    return tempPlayer; 
}
Player &Player::operator=(const Player &other)
{
    if (this == &other) { 
        return *this;
    }
    this->name = other.name;
    this->description = other.description;
    this->attacks=other.attacks;
    this->defense=other.defense;
    this->health=other.health;
    this->currentXP=other.currentXP;
    this->inventory=other.inventory;
    this->nextLevelXP=other.nextLevelXP;
    this->mana=other.mana;
    this->maxHealth=other.maxHealth;
    this->Maxmana=other.Maxmana;
    this->money=other.money;
    this->skill=other.skill;
    return *this; 
}
